package cn.tangsihai.order.service.impl;

import cn.tangsihai.basic.exception.MyException;
import cn.tangsihai.basic.query.BasicQuery;
import cn.tangsihai.basic.service.impl.BasicServiceImpl;
import cn.tangsihai.basic.util.LoginContextUtil;
import cn.tangsihai.basic.util.PageList;
import cn.tangsihai.order.domain.OrderAdress;
import cn.tangsihai.order.domain.OrderPet;
import cn.tangsihai.order.domain.OrderPetDetail;
import cn.tangsihai.order.dto.BatchOrderDto;
import cn.tangsihai.order.dto.OrderDto;
import cn.tangsihai.order.mapper.OrderAdressMapper;
import cn.tangsihai.order.mapper.OrderPetDetailMapper;
import cn.tangsihai.order.mapper.OrderPetMapper;
import cn.tangsihai.order.service.IOrderPetService;
import cn.tangsihai.org.domain.Shop;
import cn.tangsihai.pay.domain.PayBill;
import cn.tangsihai.pay.mapper.PayBillMapper;
import cn.tangsihai.pet.domain.Pet;
import cn.tangsihai.pet.domain.PetDetail;
import cn.tangsihai.pet.mapper.PetMapper;
import cn.tangsihai.quartz.job.OrderOverTimeJob;
import cn.tangsihai.quartz.service.IQuartzService;
import cn.tangsihai.shoptrolley.domain.ShopCart;
import cn.tangsihai.shoptrolley.mapper.ShopCartMapper;
import cn.tangsihai.user.domain.Logininfo;
import cn.tangsihai.user.domain.User;
import cn.tangsihai.user.domain.UserAdress;
import cn.tangsihai.user.mapper.UserAdressMapper;
import cn.tangsihai.user.mapper.UserMapper;
import jdk.internal.instrumentation.TypeMapping;
import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static cn.tangsihai.order.domain.OrderPet.ORDER_WAIT_PAY;

@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class OrderPetServiceImpl extends BasicServiceImpl<OrderPet> implements IOrderPetService {
    @Autowired
    private PetMapper petMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderPetMapper orderPetMapper;
    @Autowired
    private UserAdressMapper userAdressMapper;
    @Autowired
    private OrderPetDetailMapper orderPetDetailMapper;
    @Autowired
    private OrderAdressMapper orderAdressMapper;
    @Autowired
    private PayBillMapper payBillMapper;
    @Autowired
    private IQuartzService quartzService;
    @Autowired
    private ShopCartMapper shopCartMapper;

    @Override
    @Transactional
    public String submitOrder(OrderDto orderDto) {
        Long petId = orderDto.getPetId();
        Long payType = orderDto.getPayType();
        Long adressId = orderDto.getAdressId();
        // 1.校验非空
        if (petId == null){
            throw new MyException("商品不能为空");
        }
        if (payType == null){
            throw new MyException("支付方式不能为空");
        }
        if (adressId == null){
            throw new MyException("收货地址不能为空");
        }

        // 2.根据宠物id查询上架状态的宠物的信息
        Pet pet = petMapper.findByIdAndState(petId, Pet.ONSALE_IN_PET);
        if (pet == null){
            throw new MyException("请选择商品");
        }
        Date now = new Date();
        // 3.准备订单数据
        OrderPet orderPet = new OrderPet();
        orderPet.setDigest("宠物：" + pet.getName());
        orderPet.setState(ORDER_WAIT_PAY);
        orderPet.setTotalPrice(pet.getSaleprice());
        orderPet.setTotalCount(1);
        String orderSn = UUID.randomUUID().toString().replaceAll("-", ""); // 使用UUID生成订单编号
        orderPet.setOrderSn(orderSn);
        orderPet.setCreateTime(now);
        orderPet.setLastUpdateTime(now);
        //
        Date payExpireTime = DateUtils.addMinutes(now, 30); // 支付超时时间
        orderPet.setPayExpireTime(payExpireTime);
        Logininfo logininfo = LoginContextUtil.getLoginContext(); // 获取用户登录信息
        User logininfoUser = userMapper.findByLogininfoId(logininfo.getId()); // 获取登录用户的id
        orderPet.setUserId(logininfoUser.getId());
        orderPet.setPayType(payType);

        // 4.添加数据到数据库
        orderPetMapper.add(orderPet); // 需要返回自增长id

        // 5.准备订单明细表数据
        OrderPetDetail orderPetDetail = new OrderPetDetail();
        orderPetDetail.setName(pet.getName());
        orderPetDetail.setResources(pet.getResources());
        orderPetDetail.setPrice(pet.getSaleprice());
        orderPetDetail.setCount(1L);
        orderPetDetail.setCreatetime(now);
        orderPetDetail.setPetId(pet.getId());
        orderPetDetail.setOrderId(orderPet.getId());
        orderPetDetail.setOrderSn(orderSn);
        orderPetDetail.setShopId(pet.getShop_id());
        // 同步到数据库
        orderPetDetailMapper.add(orderPetDetail);

        // 6.准备订单地址数据，保存订单地址到数据库表中
        OrderAdress orderAdress = new OrderAdress();
        // 7.根据用户地址id查询用户地址信息
        UserAdress userAdress = userAdressMapper.loadById(adressId);
        BeanUtils.copyProperties(userAdress, orderAdress);
        orderAdress.setOrderId(orderPet.getId());
        orderAdress.setOrderSn(orderSn);
        // 保存到数据库
        orderAdressMapper.add(orderAdress);
        synchronized (this){ // 锁机制，防止超卖问题
            // 8.宠物下单完成后库存数减一，
            if (pet.getRepertory() != 0){
                pet.setRepertory(pet.getRepertory() - 1);
                // 如果商品售完就下架， 注：此时信息还没有同步到数据库，可以直接取。
                if (pet.getRepertory() == 0){
                    pet.setState(Pet.OFFSALE_IN_PET);
                }
                // 修改库存数
                petMapper.update(pet);
            } else {
                throw new MyException("商品已经卖完");
            }
        }

        // 保存支付单
        // 准备支付单数据
        PayBill payBill = new PayBill();
        payBill.setDigest(orderPet.getDigest());
        payBill.setMoney(pet.getSaleprice());
        payBill.setState(PayBill.PAYTYPE_WAIT_PAY);
        payBill.setCreateTime(now);
        payBill.setPayChannel(OrderPet.ALIPAY);
        payBill.setUpdateTime(now);
        payBill.setUnionPaySn(orderSn);
        payBill.setBusinessType(PayBill.BUSINESSTYPE_PETPAY);
        payBill.setBusinessKey(orderPet.getId());
        payBill.setUserId(logininfoUser.getId());
        payBill.setShopName(pet.getShop().getName());
        payBill.setShopId(pet.getShop_id());
        payBillMapper.add(payBill);

        // 订单超时
        String jobName = "退回超时订单：" + orderSn;
        HashMap dataMap = new HashMap();
        dataMap.put("orderSn", orderSn);
        dataMap.put("jobName", jobName);
        Date excuteTime = payExpireTime;
        quartzService.orderOverTime(jobName, OrderOverTimeJob.class, dataMap, excuteTime);
        // 返回订单号
        return orderSn;
    }

    /**
     * 批量下单
     * @param batchOrderDto
     * @return
     */
    @Override
    public List<String> batchOrder(BatchOrderDto batchOrderDto) {
        Long addressId = batchOrderDto.getAddressId();
        List<Long> cartIds = batchOrderDto.getCartIds();
        Long payType = batchOrderDto.getPayType();
        if (addressId == null){
            throw new MyException("地址不能为空");
        }
        if (cartIds == null){
            throw new MyException("商品不能为空");
        }
        if (payType == null){
            throw new MyException("支付方式不能为空");
        }

        ArrayList<String> list = new ArrayList<>();
        cartIds.forEach(cartId->{
            ShopCart shopCart = shopCartMapper.findByIdAndState(cartId, ShopCart.WAIT_PAY);
            if(shopCart == null){
                throw new MyException("请正确选择商品");
            }
            OrderDto orderDto = new OrderDto();
            orderDto.setAdressId(addressId);
            orderDto.setPayType(payType);
            orderDto.setPetId(shopCart.getPetId());
            String orderSn = submitOrder(orderDto);
            list.add(orderSn);
        });

        return list;
    }
}
